﻿using System;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using static System.Console;
using static System.Threading.Thread;

namespace Recipe8
{
    class Program
    {
        static void Main(string[] args)
        {
            Task t = AsynchronousProcessing();
            t.Wait();
        }

        static async Task AsynchronousProcessing()
        {
            var sync = new CustomAwaitTable(true);
            string result = await sync;
            WriteLine(result);

            var async = new CustomAwaitTable(false);
            result = await async;

            WriteLine(result);
        }

        class CustomAwaitTable
        {
            private readonly bool _completeSyncronously;

            public CustomAwaitTable(bool completeSynchronously)
            {
                _completeSyncronously = completeSynchronously;
            }

            public CustomAwaiter GetAwaiter()
            {
                return new CustomAwaiter(_completeSyncronously);
            }
        }

        class CustomAwaiter : INotifyCompletion
        {
            private string _result = "Completed synchronoucly";
            private readonly bool _completeSynchronously;

            public bool IsCompleted => _completeSynchronously;

            public CustomAwaiter(bool completeSynchronously)
            {
                _completeSynchronously = completeSynchronously;
            }
            public string GetResult()
            {
                return _result;
            }
            public void OnCompleted(Action continuation)
            {
                ThreadPool.QueueUserWorkItem(state =>
                {
                    Sleep(TimeSpan.FromSeconds(1));
                    _result = GetInfo();
                    continuation?.Invoke();
                });
            }

            private string GetInfo()
            {
                return $"Task is running on a thread id {CurrentThread.ManagedThreadId}. " +
                    $"Is thread pool thread: {CurrentThread.IsThreadPoolThread}";
            }
        }
    }
}
